package fidl.tool;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.franca.core.franca.FBroadcast;
import org.franca.core.franca.FInterface;
import org.franca.core.franca.FModel;

public class GeneratorInterface {

	public String prefixNameSpace = "";
	class InterfaceInfo
	{
		String name;
		String path;
		List<String> broadcasts = new ArrayList<String>();
	}
	List<InterfaceInfo> interfaces = new ArrayList<InterfaceInfo>();

	boolean doGenerate(Resource resource) {
		if (resource.getContents().isEmpty()) {
			System.out.println("An empty file: " + resource.getURI().path());
			return false;
		}
		FModel model = null;
		EObject root = resource.getContents().get(0);
		if (root instanceof FModel) {
			model = (FModel) root;
		} else {
			System.out.println("Unsupport file: " + resource.getURI().path());
			return false;
		}
		String fullNameSpace;
		if (prefixNameSpace.isEmpty()) {
			fullNameSpace = model.getName();
		} else {
			fullNameSpace = prefixNameSpace + "." + model.getName();
		}
		for (FInterface interface_ : model.getInterfaces()) {
			if (interface_.getName() == null) {
				System.out.println("Interface name can not be null.");
				continue;
			}
			String name = fullNameSpace + "." + interface_.getName();
			InterfaceInfo info = new InterfaceInfo();
			info.name = name.replace(".", "::");
			info.path = name.replace(".", "/");
			for (FBroadcast broadcast : interface_.getBroadcasts()) {
				info.broadcasts.add(broadcast.getName());
			}
			interfaces.add(info);
		}
		return true;
	}

	class Fragment
	{
		public String content;
		public boolean repeated;
		public Fragment(String content, boolean repeated) {
			this.content = content;
			this.repeated = repeated;
		}
	}

	boolean writeToFile(String outPath, String filename)
	{
		BufferedWriter writer = null;
		try {
			List<Fragment> fragments = getTemplateResource("/res/" + filename);
			filename = outPath + "/" + filename;
			File file = new File(filename);
			writer = new BufferedWriter(new FileWriter(file));
			for (Fragment fragment : fragments) {
				if (fragment.repeated) {
					writeRepeatedContent(writer, fragment.content);
				} else {
					writer.write(fragment.content);
				}
			}
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	void writeRepeatedContent(BufferedWriter writer, String fragment) throws IOException {
		for (InterfaceInfo info : interfaces) {
			String content = fragment.replace("__INTERFACE__", info.name)
									 .replace("__INTERFACE_FILE__", info.path);
			if (content.contains("__BROADCAST__")) {
				for (String broadcast : info.broadcasts) {
					content = content.replace("__BROADCAST__", broadcast);
					writer.write(content);
				}
			} else {
				writer.write(content);
			}
		}
	}

	List<Fragment> getTemplateResource(String resourceName) {
		InputStream stream = getClass().getResourceAsStream(resourceName);
		InputStreamReader streamReader = new InputStreamReader(stream);
		BufferedReader reader = new BufferedReader(streamReader);
		StringBuilder builder = new StringBuilder();
		List<Fragment> result = new ArrayList<Fragment>();
		try {
			String line;
			while ((line = reader.readLine()) != null) {
				if (line.equals("// __START_REPEATED__")) {
					result.add(new Fragment(builder.toString(), false));
					builder.setLength(0);
				} else if (line.equals("// __END_REPEATED__")) {
					result.add(new Fragment(builder.toString(), true));
					builder.setLength(0);
				} else {
					builder.append(line);
					builder.append("\n");
				}
			}
			if (!builder.isEmpty()) {
				result.add(new Fragment(builder.toString(), false));
			}
		} catch (Exception e) {
			System.out.println(e);
			result.clear();
		}
		return result;
	}
}
